﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using SIGGREProto.Util;
using GosafeTest;
using System.Data;
using System.Data.OleDb;

namespace SIGGREProto
{
    class GosafeParser
    {
        static string lastValidLongitude = "";
        static string lastValidLatitude = "";

        static string IPinternet = UtilInternet.GetExternalIP();

        static void Main(string[] args)
        {
            //testDataAvaible();

            // simulacao de duas mensagens concatenadas a primeira do tipo *HQ e a segunda do tipo binaria, 
            // comecando com hex 24 dec 36

            // 	2A-48-51-2C-39-36-36-31-31-31-32-33-30-38-2C-49-35-2C-31-38-34-34-34-31-2C-32-35-33-2C-30-2C-39-39-2C-4A-31-39-33-39-3B-54-31-46-46-46-3B-30-2D-30-30-3A-30-31-3A-33-32-2E-33-37-37-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-23
            //   *  H  Q  ,  9  6  6  1  1  1  2  3  0  8  ,  I  5  ,  184441,253,0,99,J1939;T1FFF;0-00:01:32.377;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;#
            //  *HQ,9661112308,I5,184441,253,0,99,J1939;T1FFF;0-00:01:32.377;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;#

            // 	2A-48-51-2C-39-36-36-31-31-31-32-33-30-38-2C-49-35-2C-
            //   *  H  Q  ,  9  6  6  1  1  1  2  3  0  8  ,  I  5  ,  

            // 31-38-34-34-34-31-2C-32-35-33-2C-30-2C-39-39-2C-4A-31-39-33-39-3B-54-31-46-46-46-3B-30-2D-30-30-3A-30-31-3A-33-32-2E-33-37-37-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-23
            //  1  8  4  4  4  1  ,  2  5  3  ,  0  ,99,J1939;T1FFF;0-00:01:32.377;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;#

            // 	2A-48-51-2C-39-36-36-31-31-31-32-33-30-39-2C-41-2C-32-31-35-35-34-39-2C-31-31-31-30-31-31-23-24-96-61-11-23-09-21-55-07-11-10-11-20-21-32-37-00-04-01-72-74-72-00-00-00-FF-FF-FB-FF-FF-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-08
            // *HQ,9661112309,A,215549,111011#$?a# !U !27rtr?????

            // monta strings com valores hexadecimais dos bytes do pacote de mensagens concatenadas  
            string dataReceived = "2A-48-51-2C-39-36-36-31-31-31-32-33-30-39-2C-41-2C-30-32-32-32-35-30-2C-31-32-31-30-31-31-23-";
            // posicao 31 = 24dec/36hex  posicao 32 = 96hex/150dec
            dataReceived += "24-96-61-11-23-09-02-19-52-12-10-11-20-21-29-36-00-04-01-73-01-02-00-00-00-FF-FF-FB-FF-FF-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-12";

            //  *HQ,9661112308,I5,184441,253,0,99,J1939;T1FFF;0-00:01:32.377;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;#
            dataReceived = "2A-48-51-2C-39-36-36-31-31-31-32-33-30-38-2C-49-35-2C-31-38-34-34-34-31-2C-32-35-33-2C-30-2C-39-39-2C-4A-31-39-33-39-3B-54-31-46-46-46-3B-30-2D-30-30-3A-30-31-3A-33-32-2E-33-37-37-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-23";
            // HF.OCX.7435 MERCATOR	9661112308	2011-10-18 16:00:07	-40.417664	-20.356984	0.0	0.0	BR-262 - Pista Lateral - Viana - ES, Brazil	118.855	Yes		Disarm	GPS AV	Off	Off	Off	Open	42.0	0.0	Off	Off	Off	Off	0	2685.25	42.0	20.1871	-1.0					0.0%	0.0

            //Corrigir parseamento de 3 mensagens recebidas concatenadfas em um so pacote
            //*HQ,9661112309,I5,140144,253,0,99,J1939;T1FFF;0-00:01:02.260;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;#*HQ,9661112309,I5,140154,253,0,99,J1939;T1FFF;0-00:01:12.301;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;#*HQ,9661112309,I5,140204,253,0,99,J1939;T1FFF;0-00:01:22.343;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;#*HQ,9661112309,I5,140214,253,0,99,J1939;T1FFF;0-00:01:32.384;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;#

            //9661112309	
            dataReceived = "2A-48-51-2C-39-36-36-31-31-31-32-33-30-39-2C-49-35-2C-31-34-30-31-34-34-2C-32-35-33-2C-30-2C-39-39-2C-4A-31-39-33-39-3B-54-31-46-46-46-3B-30-2D-30-30-3A-30-31-3A-30-32-2E-32-36-30-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-23-2A-48-51-2C-39-36-36-31-31-31-32-33-30-39-2C-49-35-2C-31-34-30-31-35-34-2C-32-35-33-2C-30-2C-39-39-2C-4A-31-39-33-39-3B-54-31-46-46-46-3B-30-2D-30-30-3A-30-31-3A-31-32-2E-33-30-31-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-23-2A-48-51-2C-39-36-36-31-31-31-32-33-30-39-2C-49-35-2C-31-34-30-32-30-34-2C-32-35-33-2C-30-2C-39-39-2C-4A-31-39-33-39-3B-54-31-46-46-46-3B-30-2D-30-30-3A-30-31-3A-32-32-2E-33-34-33-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-23-2A-48-51-2C-39-36-36-31-31-31-32-33-30-39-2C-49-35-2C-31-34-30-32-31-34-2C-32-35-33-2C-30-2C-39-39-2C-4A-31-39-33-39-3B-54-31-46-46-46-3B-30-2D-30-30-3A-30-31-3A-33-32-2E-33-38-34-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-23";
            //06/11/2011 12:02:19	

            // Comando V1 - posição geográfica latitude e longitude
            // *HQ,9661112309,V1,144634,A,2009.4595,S,04011.1371,W,010.00,232,051111,FEFFDFFF,FF,0000611872.36,00000000000000000000#
            string testV1 = "*HQ,9661112308,V1,144634,A,2009.4595,S,04011.1371,W,010.00,232,051111,FEFFDFFF,FF,0000611872.36,00000000000000000000#";
            byte[] testV1bytes;
            testV1bytes = UtilByte.strToByteArray(testV1);
            dataReceived = BitConverter.ToString(testV1bytes, 0, testV1bytes.Length);

            //Erro ao processar mensagem:
            //115036	2011-11-07 15:24:10.000	$?a# #X !D	
            dataReceived = "24-96-61-11-23-09-17-23-58-07-11-11-20-21-17-44-00-04-02-28-91-12-00-00-00-EF-E7-FB-FF-FF-00-00-00-84-21-01-11-00-00-00-00-00-00-00-00-00-00-16-2A-48-51-2C-39-36-36-31-31-31-32-33-30-39-2C-49-35-2C-31-37-32-34-30-35-2C-32-35-33-2C-30-2C-39-39-2C-4A-31-39-33-39-3B-54-31-46-46-46-3B-30-2D-30-30-3A-30-32-3A-32-32-2E-35-39-30-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-2A-3B-23";
            //177.19.217.126	177.63.110.20:3685	-20,3529066666667	-40,3815183333333	20º 211744'	040º 228911'	Teste paralelo Anytracking/Mercator2	9661112309	172358	071111	182

            // converte string hexa simulada vetor de bytes de mensagens concatenadas
            byte[] hexByteStringTest = UtilByte.StringToByteArray(dataReceived.Replace("-", ""));

            parsePacket(hexByteStringTest, false, IPMonitor.GetLocalIP());
        }

        // Parser baseado em metodo Split da classe String
        public static void parsePacket(byte[] packetToParse, bool disableLog, string IPDevice)
        {
            try
            {
                // separa pacote de bytes em varias mensagens,
                // cada uma um elemento de um vetor de mensagens de bytes
                byte[][] messages = parse(packetToParse);

                string HQheader="";
                string deviceID="";
                string HQcommand="";
                string dateTime="";

                string deviceDate="";
                string deviceTime="";
                string latitude="";
                string longitude="";
                string lastValidLatitude="";
                string lastValidLongitude="";
                string latitudeDec="";
                string longitudeDec="";

                bool saveLog = false;

                // testa analisador de protocolo para cada mensagem
                foreach (byte[] messageItem in messages)
                {
                    // verifica se a mensagem realmente é do tipo HQ 
                    // se for mensagem do tipo *HQ, obtem dados relevantes do protocolo 
                    if (messageItem[0] == '*' && messageItem[1] == 'H' && messageItem[2] == 'Q')
                    {
                        // obtem vetor de tokens e sub-mensagens
                        string[][] HQtokens = parseHQmessages(messageItem);

                        // TODO : por enquanto, trata apenas a primeira sub-mensagem
                        HQheader = HQtokens[0][0];
                        deviceID = HQtokens[0][1];
                        HQcommand = HQtokens[0][2];
                        deviceTime = HQtokens[0][3];
                        dateTime = DateTime.Now.ToString();

                        // Gosafe 9600A/I/SZ 7708A/7708 7709A/7709 Protocol Manual (protocol_9600_7708.pdf)
                        // 5.3 I5 multifunction interactive command
                        // Command：*HQ,YYYYYYYYYY,I5,HHMMSS,Para1,Para2,Info_len,Information#
                        // Trata proocolo HQ conforme cada comando HQcommand A, V1, I5, etc.
                        HQprotocolHandle(HQtokens);

                        if (HQcommand == "V1")
                        {
                            string latitudeStr = HQtokens[0][5];
                            string longitudeStr = HQtokens[0][7];

                            string latitudeDegreeStr = latitudeStr.Substring(0, 2);
                            string latitudeMinuteStr = latitudeStr.Substring(2);
                            latitudeMinuteStr = latitudeMinuteStr.Replace(",", "").Replace(".", "");

                            string longitudeDegreeStr = longitudeStr.Substring(0, 3);
                            string longitudeMinuteStr = longitudeStr.Substring(3);
                            longitudeMinuteStr = longitudeMinuteStr.Replace(",", "").Replace(".", "");

                            longitude = "-" + UtilMath.ConvertDegreeAngleToDouble(double.Parse(longitudeDegreeStr), double.Parse(longitudeMinuteStr) / 10000, 0).ToString();
                            latitude = "-" + UtilMath.ConvertDegreeAngleToDouble(double.Parse(latitudeDegreeStr), double.Parse(latitudeMinuteStr) / 10000, 0).ToString();

                            latitudeStr = latitudeStr.Replace(",", "");
                            longitudeStr = longitudeStr.Replace(",", "");
                            latitudeStr = latitudeStr.Replace(".", "");
                            longitudeStr = longitudeStr.Replace(".", "");
                            latitudeStr = "-" + latitudeStr.Substring(0, 2) + "," + latitudeStr.Substring(2);
                            longitudeStr = "-" + longitudeStr.Substring(0, 3) + "," + longitudeStr.Substring(3);

                            float latitudeNum;
                            float.TryParse(latitude, out latitudeNum);
                            float longitudeNum;
                            float.TryParse(longitude, out longitudeNum);

                            //latitude = latitudeNum.ToString().Replace(",",".");
                            //longitude = longitudeNum.ToString().Replace(",", ".");

                            if(latitudeNum != 0)
                                lastValidLatitude = latitude;
                            if(longitudeNum != 0)
                                lastValidLongitude = longitude;
                        }

                        saveLog = true;
                    }

                    // se for mensagem binaria
                    else if (messageItem[0] == '\x24')
                    {
                        string[] binTokens = parseBinMessages(messageItem);

                        deviceID = binTokens[0];
                        dateTime = DateTime.Now.ToString();
                        deviceDate = binTokens[1];
                        deviceTime = binTokens[2];
                        latitude = binTokens[3];
                        longitude = binTokens[4];
                        lastValidLatitude = binTokens[5];
                        lastValidLongitude = binTokens[6];
                        latitudeDec = binTokens[7];
                        longitudeDec = binTokens[8];

                        saveLog = true;
                    }

                    // mensagem de tipo desconhecido
                    else
                        Console.WriteLine(DateTime.Now + " - Erro ao parsear mensagem do tipo: <" + messageItem[0] + ">");

                    // registra quantidade total de bytes trafegados
                    int bytesQty = messageItem.Length;

                    if ((saveLog) && (!disableLog))
                        insertLogTable(messageItem, latitude, longitude, latitudeDec, longitudeDec, deviceID, deviceTime, deviceDate, bytesQty, IPDevice);

                    Console.WriteLine("DeviceID: " + deviceID + " - dateTime: " + dateTime + " - deviceTime: " + deviceTime + " - deviceDate: " +
                        deviceDate + " - latitude: " + latitude + " - longitude: " + longitude + " - latitudeDec: " + latitudeDec +
                        "longitudeDec: " + longitudeDec, IPDevice);

                    // examina cada token e monta dicionario de dados
                    //Dictionary<string, string> messageDictionary = getMessageTokens(messageItem);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(DateTime.Now + " - Erro : " + ex.Message + "\nStackTrace: " + ex.StackTrace);
                //throw;
            }

        }

        // Gosafe 9600A/I/SZ 7708A/7708 7709A/7709 Protocol Manual (protocol_9600_7708.pdf)
        // Trata proocolo HQ conforme cada comando HQcommand A, V1, I5, etc.
        private static void HQprotocolHandle(string[][] HQtokens)
        {
            try
            {
                string HQheader = HQtokens[0][0];
                string deviceID = HQtokens[0][1];
                string HQcommand = HQtokens[0][2];
                string dateTime = HQtokens[0][3];

                string param1 = "";
                string param2 = "";
                int infoLen = 0;
                string information = "";

                switch (HQcommand)
                {
                    case "A":
                        break;
                    case "V":
                        break;

                    // a cada 20 segundos - LATITUDE E LONGITUDE 
                    //*HQ,9661112309,V1,144634,A,2009.4595,S,04011.1371,W,010.00,232,051111,FEFFDFFF,FF,0000611872.36,00000000000000000000#
                    case "V1": // mensagem de latitude e longigute

                        break;

                    // 5.3 I5 multifunction interactive command
                    // Command：*HQ,YYYYYYYYYY,I5,HHMMSS,Para1,Para2,Info_len,Information#
                    //Parameter definition：
                    //Parameter 1：0- 65535
                    //Parameter 2：0-255
                    //Info_len: the length of information, the range：1-256
                    //G o s a f e C o m p a n y L i m i t e d Page
                    //Gosafe Protocol
                    //Information: information content
                    //Example: message: @1234
                    //Send:
                    //*HQ,1234567890,I5,000000,255,0,4,A001#
                    case "I5":
                        param1 = HQtokens[0][4];
                        param2 = HQtokens[0][5];
                        int.TryParse(HQtokens[0][6], out infoLen);
                        if (infoLen > 0)
                            information = HQtokens[0][7];

                        break;
                    default:
                        break;
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(DateTime.Now + " - Erro : " + ex.Message + "\nStackTrace: " + ex.StackTrace);
                //throw;
            }
        }

        // Parser baseado em metodo Split da classe String
        // TODO : usar recursividade para obter mensagens duplicadas concatenadas do mesmo tipo
        public static byte[][] parse(byte[] bytesToParse)
        {
            // vetor de bytes de mensagens obtidas da quebra do pacote
            byte[][] messagesBytes = null;

            try
            {
                // teste de reversão de bytes - desconsiderar esta linha por enquanto
                string bytesString = System.Text.Encoding.ASCII.GetString(bytesToParse);

                // TODO : usar recursividade para obter mensagens duplicadas concatenadas do mesmo tipo
                // em messageItem pode haver mais de uma mensagem do mesmo tipo *HQ concatenada

                // separa mensagens no pactoe paseado no caracter de inicio de mensagem binaria, caracter $ decimal 36 hexa 24
                string[] messagesArray = bytesString.Split(new Char[] { '\x24' });

                // vetor de tamanhos de mensagens
                int messagesLen = 0;// new int[messagesArray.Length];

                // inicializa vetor de bytes de mensagens obtidas da quebra do pacote
                messagesBytes = new byte[messagesArray.Length][];

                // contador de mensagens lidas dentro do pacote de bytes
                int messagesLenCounter = 0;

                // ponteiro para posição de inicio da mensagem atual dentro do vetor de bytes do pacote inteiro
                int cursorMessageStartPosition = 0;

                // primeiro percorre vetor de mensagens separadas por Split 
                // para ober o tamanho de cada mensagem num array de tamanhos
                foreach (string messageItem in messagesArray)
                {
                    // TODO : usar recursividade para obter mensagens duplicadas concatenadas do mesmo tipo
                    // em messageItem pode haver mais de uma mensagem do mesmo tipo *HQ concatenada

                    // teste de reversão de bytes - desconsiderar esta linha por enquanto
                    //byte[] test = (new System.Text.ASCIIEncoding()).GetBytes(messageItem);

                    // param mensagens que não sejam binarias, ou seja,
                    // que sejam tipo *HQ, o tamanho já inclui o byte inicial 
                    if (messageItem.ToCharArray()[0] == '*')
                        messagesLen = messageItem.Length;

                    // caso seja uma mensagem do tipo binaria, soma mais um para consigerar o caracter hexa 24 que foi retirado no metodo Split
                    // e reinsere o caracter de inicio de mensagem na primeira posição da mensagem
                    else
                        messagesLen = messageItem.Length + 1;

                    // reserva bytes na memoria para mensagem
                    Array.Resize(ref messagesBytes[messagesLenCounter], messagesLen);

                    // copia trecho do pacote que contem a mensagem para o vetor de bytes de mensagens separadas
                    Array.Copy(bytesToParse, cursorMessageStartPosition, messagesBytes[messagesLenCounter], 0, messagesLen);

                    // resposiciona ponteiro para posição de inicio da mensagem atual dentro do vetor de bytes do pacote inteiro
                    cursorMessageStartPosition += messagesLen;
                    
                    // incrementa contador de mensagens
                    messagesLenCounter++;
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(DateTime.Now + " - Erro : " + ex.Message + "\nStackTrace:" + ex.StackTrace);
                //throw;
            }
                
            return messagesBytes;

        }

        // parser baseado em máquina de estado que analisa byte a byte
        public static void testMessageParserByte()
        {
            string dataReceived = "2A-48-51-2C-39-36-36-31-31-31-32-33-30-39-2C-41-2C-30-32-32-32-35-30-2C-31-32-31-30-31-31-23-";
            // posicao 31 = 24dec/36hex  posicao 32 = 96hex/150dec
            dataReceived += "24-96-61-11-23-09-02-19-52-12-10-11-20-21-29-36-00-04-01-73-01-02-00-00-00-FF-FF-FB-FF-FF-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-12";

            byte[] hexByteString = UtilByte.StringToByteArray(dataReceived.Replace("-", ""));

            byte[][] HQmessagesBytes;
            byte[][] binaryMessagesBytes;

            // flags de inicio e fim de mensagem binaria
            bool startBinaryMessage = false;
            bool endBinaryMesssage = false;

            // flags de inicio e fim de mensagem *HQ
            bool startHQmessage = false;
            bool endHQmessage = false;

            // flag d inicio de mensagem desconhecida
            bool startUnknownMessage = false;

            // contador de bytes da mensagem
            int messageByteCounter = -1;

            // máquina de estado para separar o pacote de bytes recebidos em mensagens
            foreach (byte byteItem in hexByteString)
            {
                byte[] messageItem;
                messageByteCounter++;

                // verifica e trata cada um dos estados atuais da maquina de estado:

                // se estiver lendo mensagem do tipo binaria que comeca com hexa 24 ou decimal 36
                if (startBinaryMessage)
                {

                }

                // se estiver lendo mensagem do tipo *HQ
                else if (startHQmessage)
                {

                }

                // se estiver lendo mensagem desconhecida
                else if (startUnknownMessage)
                {

                }

                // caso tenha finalizado uma mensagem do tipo binaria
                else
                {

                }

                // se for mensagem do tipo *HQ
                //if (hexByteString[0] == '*' && hexByteString[1] == 'H' && hexByteString[2] == 'Q')
                if (byteItem == '*' && hexByteString[messageByteCounter + 1] == 'H' && hexByteString[messageByteCounter + 2] == 'Q')
                {
                    // sinaliza flag de inicio de mensagem binaria
                    startBinaryMessage = true;
                }

                // mensagem começa com hexa 24 ou decima 36 então é inicio de mensagem binaria
                else if (byteItem == '\x24')
                {
                    startHQmessage = true;
                }

                // mensagem não reconhecida para protocolo Gosafe
                else
                {
                    startUnknownMessage = true;
                }
            }

        }

        // antigo parser que nao separava mensagens multiplas no mesmo pacote
        public static void oldParser(byte[] message, bool saveLog)
        {
            try
            {
                byte[] messageReceived = new byte[message.Length];
                message.CopyTo(messageReceived, 0);

                //messageReceived = new byte[message.Length];
                //message.CopyTo(this.messageReceived, 0);

                //char[] cArray = System.Text.Encoding.ASCII.GetString(messageReceived).ToCharArray();

                string bytesString = System.Text.Encoding.ASCII.GetString(messageReceived);
                string bytesASCII = BitConverter.ToString(messageReceived, 0, messageReceived.Length);
                Console.WriteLine(DateTime.Now + " Bytes Received: " + bytesASCII);

                string longitude = ""; string latitude = "";
                string latitudeDec = ""; string longitudeDec = "";

                string bytesASCIIstr = bytesASCII.Replace("-", ""); // remove separadores dos bytes ASCII

                string messageType = bytesASCIIstr.Substring(0, 2);

                string obs = "";
                string deviceID = ""; // Numero de série de identificação do dispositivo embarcado    
                string deviceTime = "";
                string deviceDate = "";

                // Verifica se o tipo de mensagem é de latitude e longitude
                if (message[0] == 36)
                {
                    try
                    {
                        deviceID = bytesASCIIstr.Substring(2, 10);
                        Console.WriteLine(DateTime.Now + "DeviceID: " + deviceID);

                        deviceTime = bytesASCIIstr.Substring(12, 6);
                        Console.WriteLine(DateTime.Now + "deviceTime: " + deviceTime);

                        deviceDate = bytesASCIIstr.Substring(18, 6);
                        Console.WriteLine(DateTime.Now + "deviceDate: " + deviceDate);

                        obs = "DeviceID: " + deviceID + " - deviceTime: " + deviceTime + " - deviceDate: " + deviceDate;

                        //24-96-61-11-23-09-13-09-51-10-09-11-  20-21-30-22-00-     04-01-73-03-02-00-00-00-FF-FF-FB-FF-FF-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-04
                        //                              12+4    2021.3083  S   17+4 04017.3066 W     
                        latitude = BitConverter.ToString(message, 12, 2).Replace("-", "") + "." + BitConverter.ToString(message, 14, 2).Replace("-", "") + "'";
                        longitude = BitConverter.ToString(message, 17, 2).Replace("-", "") + BitConverter.ToString(message, 19, 3).Replace("-", "") + "'";
                        //longitude = longitude.Substring(0, 5) + "." + longitude.Substring(5, 2);
                        //longitude = longitude.Substring(0, 5)  + longitude.Substring(5, 2);
                        longitude = longitude.Substring(0, 5) + longitude.Substring(5, 4);
                        Console.WriteLine(DateTime.Now + " Latitude + Longitude: " + latitude + " - " + longitude);

                        string latitudeDegreeStr = BitConverter.ToString(message, 12, 1).Replace("-", "");
                        //string latitudeMinuteStr = BitConverter.ToString(message, 13, 1).Replace("-", "") + "." + BitConverter.ToString(message, 14, 2).Replace("-", "");
                        string latitudeMinuteStr = BitConverter.ToString(message, 13, 1).Replace("-", "") + BitConverter.ToString(message, 14, 2).Replace("-", "");

                        string longitudeDegreeStr = longitude.Substring(0, 3).Replace("-", "");
                        //string longitudeMinuteStr = longitude.Substring(3, 2).Replace("-", "") + "." + BitConverter.ToString(message, 5, 2).Replace("-", "");
                        //string longitudeMinuteStr = longitude.Substring(3, 2).Replace("-", "") + BitConverter.ToString(message, 5, 2).Replace("-", "");
                        string longitudeMinuteStr = longitude.Substring(3, 6).Replace("-", "");
                        //longitudeMinuteStr = longitudeMinuteStr.Substring(3, 8);

                        //latitudeMinuteStr += "." + BitConverter.ToString(message, 14, 2).Replace("-", "");
                        //longitudeMinuteStr += "." + BitConverter.ToString(message, 5, 2).Replace("-", "");

                        Console.WriteLine(DateTime.Now + " Latitude: " + latitudeDegreeStr + "º " + latitudeMinuteStr + "'");
                        Console.WriteLine(DateTime.Now + " Longitude: " + longitudeDegreeStr + "º " + longitudeMinuteStr + "'");

                        longitude = longitudeDegreeStr + "º " + longitudeMinuteStr + "'";
                        latitude = latitudeDegreeStr + "º " + latitudeMinuteStr + "'";

                        latitudeDec = latitude;
                        longitudeDec = longitude;

                        Console.WriteLine(DateTime.Now + " Longitude: " + UtilMath.ConvertDegreeAngleToDouble(double.Parse(longitudeDegreeStr), double.Parse(longitudeMinuteStr) / 10000, 0));
                        Console.WriteLine(DateTime.Now + " latitude: " + UtilMath.ConvertDegreeAngleToDouble(double.Parse(latitudeDegreeStr), double.Parse(latitudeMinuteStr) / 10000, 0));

                        longitude = "-" + UtilMath.ConvertDegreeAngleToDouble(double.Parse(longitudeDegreeStr), double.Parse(longitudeMinuteStr) / 10000, 0).ToString();
                        latitude = "-" + UtilMath.ConvertDegreeAngleToDouble(double.Parse(latitudeDegreeStr), double.Parse(latitudeMinuteStr) / 10000, 0).ToString();

                        lastValidLatitude = latitude;
                        lastValidLongitude = longitude;
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine(DateTime.Now + " - Erro : " + ex.Message + "\nStackTrace: " + ex.StackTrace);
                        //throw;
                    }
                }

                if ((latitude == null) || (latitude.Trim().Length == 0))
                    latitude = lastValidLatitude;

                if ((longitude == null) || (longitude.Trim().Length == 0))
                    longitude = lastValidLongitude;

                if (saveLog)
                {
                    //dtLog.Rows.Add(null, DateTime.Now, bytesString, bytesASCII, IPinternet, IPDevice, latitude, longitude, latitudeDec,
                    //    longitudeDec, obs, deviceID, deviceTime, deviceDate);
                    //saveLogTable(logDA);
                }

                Console.WriteLine("DeviceID: " + deviceID + " - deviceTime: " + deviceTime + " - deviceDate: " + deviceDate);

                if ((deviceID != null) && (deviceID.Trim() != ""))
                {
                    int bytesQty = message.Length;

                    //if (saveLog)
                    //    SaveDeviceTable(DateTime.Now, bytesString, bytesASCII, IPinternet, IPDevice, latitude, longitude, latitudeDec,
                    //        longitudeDec, obs, deviceID, deviceTime, deviceDate, bytesQty);

                    Console.WriteLine(DateTime.Now + " - Device atualizado");
                }

                // Verifica se o tipo de mensagem é de *HQ *= 42 dec ou 2A hexa
                if (message[0] == 42)
                {
                    string emailBody = "Prezado usuário, \n\tEste é um aviso automático do Servidor Mercator 2.0. \n\n\tPor favor, não responda a este e-mail.";
                    emailBody += "\n\n\tEndereço IP do servidor Mercator ativo: " + IPinternet;
                    emailBody += "\n\n\tMensagem recebida do dispositivo embarcado de número <" + deviceID +
                        "> acabou de RE-CONECTAR no servidor Mercator da Lifeware";
                    emailBody += "\n\n\t A mensagem de pedido de reconexão foi: " + bytesString;
                    emailBody += "\n\n\t Os últimos dados válidos recebidos desse dispsoitivo foram: ";
                    emailBody += "\n\n\tData Hora: " + DateTime.Now;
                    emailBody += "\n\n\tLatitude e Longitude: " + lastValidLatitude + "/" + lastValidLongitude;
                    emailBody += "\n\n\tEndereço: " + "<funcionalidade em desenvolvimento>";

                    //GosafeRelayTest.UtilMail.SendGmail("gerson.freire@gmail.com", "gersonfaf61", "gerson.freire@gmail.com",
                    //    "mercator2web@gmail.com", "mercator2web@gmail.com", "Lifeware Mercator 2.0 - Notificação automática", emailBody, false);

                    Console.WriteLine(DateTime.Now + " RE-Connection notification e-mail sent ...");
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(DateTime.Now + " - Erro : " + ex.Message + "\nStackTrace:" + ex.StackTrace);
                //throw;
            }
        }

        // parser de mensagens do tipo *HQ
        public static string[][] parseHQmessages(byte[] message)
        {
            string[][] HQtokens = null;

            try
            {
                // converte bytes da mensagem para string
                string messageString = System.Text.Encoding.ASCII.GetString(message);

                // quebra a mensagem *HQ em varias para o caso de haver multiplas mensagens 
                string[] HQmessages = messageString.Split(new Char[] {'#'}, StringSplitOptions.RemoveEmptyEntries);

                // inicializa e reserva itens do vetor
                HQtokens = new string[HQmessages.Length][];

                // contador de mensagens
                int messageCounter = 0;

                // percorre cada mensagem e obtem os dados relevantes
                foreach (string HQmessageItem in HQmessages)
                {
                    // verifica se a mensagem realmente é do tipo HQ 
                    if (HQmessageItem.Substring(0, 3) == "*HQ")
                        // separa tokens da mensagem
                        HQtokens[messageCounter++] = HQmessageItem.Split(',');

                    // TODO : caso não seja, ignora mensagem e reporta erro
                    else
                        Console.WriteLine(DateTime.Now + " - Erro ao parsear mensagem: <" + HQmessageItem + ">"); 
                }

            }
            catch (Exception ex)
            {
                Console.WriteLine(DateTime.Now + " - Erro : " + ex.Message + "\nStackTrace: " + ex.StackTrace);
                //throw;
            }

            return HQtokens;
        }

        // antigo parser que nao separava mensagens multiplas no mesmo pacote
        public static string[] parseBinMessages(byte[] message)
        {
            string[] tokens = null;

            try
            {
                byte[] messageReceived = new byte[message.Length];
                message.CopyTo(messageReceived, 0);

                //messageReceived = new byte[message.Length];
                //message.CopyTo(this.messageReceived, 0);

                //char[] cArray = System.Text.Encoding.ASCII.GetString(messageReceived).ToCharArray();

                string bytesString = System.Text.Encoding.ASCII.GetString(messageReceived);
                string bytesASCII = BitConverter.ToString(messageReceived, 0, messageReceived.Length);
                Console.WriteLine(DateTime.Now + " Bytes Received: " + bytesASCII);

                string longitude = ""; string latitude = "";
                string latitudeDec = ""; string longitudeDec = "";

                string bytesASCIIstr = bytesASCII.Replace("-", ""); // remove separadores dos bytes ASCII

                string messageType = bytesASCIIstr.Substring(0, 2);

                string obs = "";
                string deviceID = ""; // Numero de série de identificação do dispositivo embarcado    
                string deviceTime = "";
                string deviceDate = "";

                // Verifica se o tipo de mensagem é de latitude e longitude
                if (message[0] == 36)
                {
                    try
                    {
                        deviceID = bytesASCIIstr.Substring(2, 10);
                        Console.WriteLine(DateTime.Now + "DeviceID: " + deviceID);

                        deviceTime = bytesASCIIstr.Substring(12, 6);
                        Console.WriteLine(DateTime.Now + "deviceTime: " + deviceTime);

                        deviceDate = bytesASCIIstr.Substring(18, 6);
                        Console.WriteLine(DateTime.Now + "deviceDate: " + deviceDate);

                        obs = "DeviceID: " + deviceID + " - deviceTime: " + deviceTime + " - deviceDate: " + deviceDate;

                        //24-96-61-11-23-09-13-09-51-10-09-11-  20-21-30-22-00-     04-01-73-03-02-00-00-00-FF-FF-FB-FF-FF-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-04
                        //                              12+4    2021.3083  S   17+4 04017.3066 W     
                        latitude = BitConverter.ToString(message, 12, 2).Replace("-", "") + "." + BitConverter.ToString(message, 14, 2).Replace("-", "") + "'";
                        longitude = BitConverter.ToString(message, 17, 2).Replace("-", "") + BitConverter.ToString(message, 19, 3).Replace("-", "") + "'";
                        longitude = longitude.Substring(0, 5) + longitude.Substring(5, 4);
                        Console.WriteLine(DateTime.Now + " Latitude + Longitude: " + latitude + " - " + longitude);

                        string latitudeDegreeStr = BitConverter.ToString(message, 12, 1).Replace("-", "");
                        string latitudeMinuteStr = BitConverter.ToString(message, 13, 1).Replace("-", "") + BitConverter.ToString(message, 14, 2).Replace("-", "");

                        string longitudeDegreeStr = longitude.Substring(0, 3).Replace("-", "");
                        string longitudeMinuteStr = longitude.Substring(3, 6).Replace("-", "");

                        Console.WriteLine(DateTime.Now + " Latitude: " + latitudeDegreeStr + "º " + latitudeMinuteStr + "'");
                        Console.WriteLine(DateTime.Now + " Longitude: " + longitudeDegreeStr + "º " + longitudeMinuteStr + "'");

                        longitude = longitudeDegreeStr + "º " + longitudeMinuteStr + "'";
                        latitude = latitudeDegreeStr + "º " + latitudeMinuteStr + "'";

                        latitudeDec = latitude;
                        longitudeDec = longitude;

                        Console.WriteLine(DateTime.Now + " Longitude: " + UtilMath.ConvertDegreeAngleToDouble(double.Parse(longitudeDegreeStr), double.Parse(longitudeMinuteStr) / 10000, 0));
                        Console.WriteLine(DateTime.Now + " latitude: " + UtilMath.ConvertDegreeAngleToDouble(double.Parse(latitudeDegreeStr), double.Parse(latitudeMinuteStr) / 10000, 0));

                        longitude = "-" + UtilMath.ConvertDegreeAngleToDouble(double.Parse(longitudeDegreeStr), double.Parse(longitudeMinuteStr) / 10000, 0).ToString();
                        latitude = "-" + UtilMath.ConvertDegreeAngleToDouble(double.Parse(latitudeDegreeStr), double.Parse(latitudeMinuteStr) / 10000, 0).ToString();

                        tokens=new string[10];
                        tokens[0] = deviceID;
                        tokens[1] = deviceDate;
                        tokens[2] = deviceTime;
                        tokens[3] = latitude;
                        tokens[4] = longitude;
                        tokens[5] = lastValidLatitude;
                        tokens[6] = lastValidLongitude;
                        tokens[7] = latitudeDec;
                        tokens[8] = longitudeDec;

                        lastValidLatitude = latitude;
                        lastValidLongitude = longitude;
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine(DateTime.Now + " - Erro : " + ex.Message + "\nStackTrace: " + ex.StackTrace);
                        //throw;
                    }
                }

                if ((latitude == null) || (latitude.Trim().Length == 0))
                    latitude = lastValidLatitude;

                if ((longitude == null) || (longitude.Trim().Length == 0))
                    longitude = lastValidLongitude;

                Console.WriteLine("DeviceID: " + deviceID + " - deviceTime: " + deviceTime + " - deviceDate: " + deviceDate);
            }
            catch (Exception ex)
            {
                Console.WriteLine(DateTime.Now + " - Erro : " + ex.Message + "\nStackTrace:" + ex.StackTrace);
                //throw;
            }

            return tokens;
        }

        // examina cada token e monta dicionario de dados
        public static Dictionary<string, string> getMessageTokens(byte[] messageItem)
        {
            // examina cada token e monta dicionario de dados
            Dictionary<string, string> messageDictionary = new Dictionary<string, string>();

            try
            {
                // teste com parser antigo que nao separa mensagens do pacote
                //parseMessage(messageItem, false);

                // tokens da mensagem HQ
                string[][] HQtokens = null;

                // se for mensagem do tipo *HQ, obtem dados relevantes do protocolo 
                if (messageItem[0] == '*' && messageItem[1] == 'H' && messageItem[2] == 'Q')
                {
                    HQtokens = parseHQmessages(messageItem);

                    // TODO : por enquanto, trata apenas a primeira mensagem
                    string HQheader = HQtokens[0][0];
                    string HQdeviceID = HQtokens[0][1];
                    string HQcommand = HQtokens[0][2];
                    string HQdateTime = HQtokens[0][3];

                    // examina cada token e monta dicionario de dados
                    Dictionary<string, string> HQdictionary = new Dictionary<string, string>();

                    string[] dictionaryKeys = new string[] { "DeviceID", "CommandCode", "DateTime", "Param1", "Param2", "Info_Len", "Information" };
                    //foreach (string tokenItem in HQtokens)
                    foreach (string keyItem in dictionaryKeys)
                    {
                        //HQdictionary.Add(keyItem,
                    }
                }

                /*
                    *HQ,9661112308,I5,183434,253,0,99,J1939;T1FFF;0-00:03:42.903;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;*;#
                 
                    * Command：*HQ,YYYYYYYYYY,I5,HHMMSS,Para1,Para2,Info_len,Information#
                    Parameter definition：
                    Parameter 1：0- 65535
                    Parameter 2：0-255
                    Info_len: the length of information, the range：1-256
                    G o s a f e C o m p a n y L i m i t e d Page
                    Gosafe Protocol
                    Information: information content
                    Example: message: @1234
                    Send:
                    *HQ,1234567890,I5,000000,255,0,4,A001#
                    * 
                    */

                // trata mensagem do tipo binario
                else if (messageItem[0] == '\x24')
                {
                    oldParser(messageItem, false);
                }

                // mensagem de tipo desconhecido
                else
                {
                    Console.WriteLine(DateTime.Now + " - Erro ao parsear mensagem do tipo: <" + messageItem[0] + ">");
                }

            }
            catch (Exception ex)
            {
                Console.WriteLine(DateTime.Now + " - Erro : " + ex.Message + "\nStackTrace: " + ex.StackTrace);
                //throw;
            }

            return messageDictionary;
        }

        //public void saveLogTable(System.Data.OleDb.OleDbDataAdapter currentDBAdapter)
        public static void saveLogTable()
        {
            try
            {
                WindowsFormsApplication1.GenericDatabase logDB = null;
                //string connString = "Provider=SQLOLEDB.1;Password=life2011;Persist Security Info=True;User ID=sa;Initial Catalog=MERCATOR_hist;Data Source=www.lifeware.com.br\\sqlexpress,2272";
                string connString = "Provider=SQLOLEDB.1;Password=life2011;Persist Security Info=True;User ID=sa;Initial Catalog=MERCATOR_hist;Data Source=192.168.1.101\\sqlexpress,2272";
                
                logDB = new WindowsFormsApplication1.GenericDatabase();
                logDB.Open(connString);

                System.Data.OleDb.OleDbDataAdapter logDA = null;
                System.Data.DataSet logDataSet = null;
                object cmdBuilder = null;

                System.Data.OleDb.OleDbCommand tableCommand =
                    new System.Data.OleDb.OleDbCommand("SELECT * FROM " + "RelayLog",
                  ((System.Data.OleDb.OleDbConnection)logDB.Connection));

                logDataSet = new System.Data.DataSet();

                logDA = new System.Data.OleDb.OleDbDataAdapter(tableCommand);

                logDA.Fill(logDataSet);
                if (logDA.GetType() == (new System.Data.OleDb.OleDbDataAdapter()).GetType())
                {
                    cmdBuilder = new System.Data.OleDb.OleDbCommandBuilder((System.Data.OleDb.OleDbDataAdapter)logDA);
                    ((System.Data.OleDb.OleDbCommandBuilder)cmdBuilder).GetUpdateCommand();
                    logDA.Update(logDataSet);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(DateTime.Now + " - Erro : " + ex.Message + "\nStackTrace: " + ex.StackTrace);
                //throw;
            }
        }

        public static void insertLogTable(byte[] messageItem, string latitude, string longitude, string latitudeDec,
                string longitudeDec, string deviceID, string deviceTime, string deviceDate, int bytesQty, string IPDevice)
        {

            try
            {
                string bytesString = System.Text.Encoding.ASCII.GetString(messageItem);
                string bytesASCII = BitConverter.ToString(messageItem, 0, messageItem.Length);

                string localIP = IPMonitor.GetLocalIP();

                WindowsFormsApplication1.GenericDatabase logDB = null;

                string connString = "";
                if(IPDevice!="192.168.1.101")
                    connString = "Provider=SQLOLEDB.1;Password=life2011;Persist Security Info=True;User ID=sa;Initial Catalog=MERCATOR_hist;Data Source=www.lifeware.com.br\\sqlexpress,2272";
                else
                    connString = "Provider=SQLOLEDB.1;Password=life2011;Persist Security Info=True;User ID=sa;Initial Catalog=MERCATOR_hist;Data Source=192.168.1.101\\sqlexpress,2272";

                Console.WriteLine(DateTime.Now + " - Abrindo conexao ao banco de dados: <" + connString + ">, aguarde...");

                logDB = new WindowsFormsApplication1.GenericDatabase();
                logDB.Open(connString);

                Console.WriteLine(DateTime.Now + " - Conexão ao banco de dados aberta com sucesso!");

                System.Data.OleDb.OleDbDataAdapter logDA = null;
                System.Data.DataSet logDataSet = null;

                System.Data.OleDb.OleDbCommand tableCommand =
                    new System.Data.OleDb.OleDbCommand("SELECT TOP 1 * FROM " + "RelayLog",
                    //new System.Data.OleDb.OleDbCommand("SELECT * FROM " + "RelayLog",
                  ((System.Data.OleDb.OleDbConnection)logDB.Connection));

                //getLogData("RelayLog");
                logDataSet = new System.Data.DataSet();
                logDA = new System.Data.OleDb.OleDbDataAdapter(tableCommand);

                Console.WriteLine(DateTime.Now + " - Obtendo dados da tabela: <RelayLog>, aguarde...");
                logDA.Fill(logDataSet);
                Console.WriteLine(DateTime.Now + " - Tabela: <RelayLog>, obtida com sucesso!");

                System.Data.DataTable dtLog = logDataSet.Tables[0];

                DataRow logRow = dtLog.NewRow();
                logRow["ReceivedDateTime"] = DateTime.Now.ToString();
                logRow["ReceivedBytes"] = bytesString;
                logRow["ReceivedASCII"] = bytesASCII;
                logRow["ServerIP"] = IPinternet;
                logRow["DeviceIP"] = IPDevice;
                logRow["Latitude"] = latitude;
                logRow["Longitude"] = longitude;
                logRow["LatitudeDecimal"] = latitudeDec;
                logRow["LongitudeDecimal"] = longitudeDec;
                logRow["Obs"] = "Teste paralelo Anytracking/Mercator2";
                logRow["DeviceID"] = deviceID;
                logRow["DeviceTime"] = deviceTime;
                logRow["DeviceDate"] = deviceDate;
                logRow["ReceivedByteLength"] = messageItem.Length;

                dtLog.Rows.Add(logRow);

                //dtLog.Rows.Add(null, DateTime.Now, bytesString, bytesASCII, IPinternet, IPDevice, latitude, longitude, latitudeDec,
                //    longitudeDec, "Observações: teste em paralelo Anytracking/Mercator2", deviceID, deviceTime, deviceDate);

                //saveLogTable();
                if (logDA.GetType() == (new System.Data.OleDb.OleDbDataAdapter()).GetType())
                {
                    System.Data.OleDb.OleDbCommandBuilder cmdBuilder = new System.Data.OleDb.OleDbCommandBuilder((System.Data.OleDb.OleDbDataAdapter)logDA);
                    ((System.Data.OleDb.OleDbCommandBuilder)cmdBuilder).GetUpdateCommand();

                    Console.WriteLine(DateTime.Now + " - Inserindo dados na tabela: <RelayLog>, aguarde...");
                    logDA.Update(logDataSet);
                    Console.WriteLine(DateTime.Now + " - Dados inseridos na Tabela <RelayLog> com sucesso!");

                    // atualiza tabela de dispositivos
                    SaveDeviceTable(logDB, DateTime.Now,bytesString,bytesASCII,IPinternet,IPDevice,latitude,longitude,
                        latitudeDec, longitudeDec, "Obs.:", deviceID, deviceTime, deviceDate, bytesQty);
                }
            }
            catch (Exception ex)
            {

                //throw;
            }
        }

        private static void SaveDeviceTable( WindowsFormsApplication1.GenericDatabase logDB,
            DateTime dateTime, string bytesString, string bytesASCII,
            string IPinternet, string IPDevice, string latitude, string longitude, string latitudeDec,
            string longitudeDec, string obs, string deviceID, string deviceTime, string deviceDate,
            int bytesQty)
        {
            try
            {
                System.Data.OleDb.OleDbDataAdapter currentDataAdapter = null;

                DataTable dtDevice = null;

                // Insere ou atualiza dados na tabela de dispositivos

                // Primeiro, verifica se dispositivo já está cadastrado
                DataSet deviceDS = getData(logDB, "Device", " DeviceID='" + deviceID + "'");

                dtDevice = deviceDS.Tables[0];

                // Se dispositivo já existe no cadastro
                if ((deviceDS.Tables.Count > 0) && (deviceDS.Tables[0].Rows.Count > 0))
                {
                    dtDevice.Rows[0]["ServerIP"] = IPinternet;
                    dtDevice.Rows[0]["DeviceIP"] = IPDevice;
                    dtDevice.Rows[0]["LastUploadDate"] = DateTime.Today.ToString();
                    dtDevice.Rows[0]["LastUploadTime"] = DateTime.Now.ToString();

                    dtDevice.Rows[0]["DeviceTime"] = deviceTime;

                    dtDevice.Rows[0]["LastReceivedBytes"] = bytesString;

                    int bytesQtyOld = 0;
                    if (int.TryParse(dtDevice.Rows[0]["TotalBytesReceivedDay"].ToString(), out bytesQtyOld))
                        bytesQtyOld += bytesQty;
                    dtDevice.Rows[0]["TotalBytesReceivedDay"] = bytesQtyOld;
                    if (int.TryParse(dtDevice.Rows[0]["TotalBytesReceivedMonth"].ToString(), out bytesQtyOld))
                        bytesQtyOld += bytesQty;
                    dtDevice.Rows[0]["TotalBytesReceivedMonth"] = bytesQtyOld;

                    double lastLongitude = 0;
                    double lastLatitude = 0;

                    if (double.TryParse(longitude.Replace(",", "."), out lastLongitude))
                        dtDevice.Rows[0]["LastLongitude"] = longitude;

                    if (double.TryParse(latitude.Replace(",", "."), out lastLatitude))
                        dtDevice.Rows[0]["LastLatitude"] = latitude;
                }
                // Caso contrário insere novo dispositivo com dados atualizados
                else
                {

                    dtDevice.Rows.Add(deviceID, "", "", IPinternet, IPDevice, "", longitude, latitude,
                       "", "", DateTime.Today.ToString(), DateTime.Now.ToString(), "3030", "1", 0, 0);
                }

                string SQL = "SELECT * FROM Device";
                OleDbCommand tableCommand = new OleDbCommand(SQL, (OleDbConnection)logDB.Connection);

                currentDataAdapter = new OleDbDataAdapter(tableCommand);

                // Salva alterações na tabela física subjacente
                OleDbCommandBuilder cmdBuilder = new OleDbCommandBuilder(currentDataAdapter);
                
                OleDbCommand  updateCommand = cmdBuilder.GetUpdateCommand();

                currentDataAdapter.Update(deviceDS);


            }
            catch (Exception ex)
            {
                Console.WriteLine(DateTime.Now + " - Erro : " + ex.Message + "\nStackTrace:" + ex.StackTrace);
                //throw;
            }
        }

        public static DataSet getData( WindowsFormsApplication1.GenericDatabase logDB, string currentTableName, string whereClause)
        {
            System.Data.DataSet tempDataSet = new System.Data.DataSet();

            try
            {
                string SQL = "SELECT * FROM " + currentTableName;
                if ((whereClause != null) && (whereClause.Trim() != ""))
                    SQL += " WHERE " + whereClause;

                System.Data.OleDb.OleDbCommand tableCommand =
                      new System.Data.OleDb.OleDbCommand(SQL,
                          ((System.Data.OleDb.OleDbConnection)logDB.Connection));

                System.Data.OleDb.OleDbDataAdapter currentDataAdapter = new System.Data.OleDb.OleDbDataAdapter(tableCommand);

                currentDataAdapter.Fill(tempDataSet);
            }
            catch (Exception ex)
            {
                Console.WriteLine(DateTime.Now + " - Erro : " + ex.Message + "\nStackTrace:" + ex.StackTrace);
                //throw;
            }

            return tempDataSet;
        }

    }
}

// campos da tabela de log
//ID	int	Unchecked
//ReceivedDateTime	datetime	Unchecked
//ReceivedBytes	varchar(4096)	Unchecked
//ReceivedASCII	text	Unchecked
//ServerIP	varchar(50)	Unchecked
//DeviceIP	varchar(50)	Checked
//Latitude	varchar(50)	Checked
//Longitude	varchar(50)	Checked
//LatitudeDecimal	varchar(50)	Checked
//LongitudeDecimal	varchar(50)	Checked
//Obs	text	Checked
//DeviceID	varchar(50)	Checked
//DeviceTime	varchar(50)	Checked
//DeviceDate	varchar(50)	Checked
